<?php
/**
 * FastApp.
 * 10/23/24
 * @Author deepsea159
 * @Contact telegram:deepsea159
 */

namespace App\Fastapp;

use App\Fastapp\Api\Temp\TplMall;
use App\Fastapp\Exception\TipException;
use App\Fastapp\Model\AccountLoginLog;
use App\Fastapp\Model\FastappChannel;
use PHPMailer\PHPMailer\PHPMailer;

class FastappEmailService
{
    const PREFIX = 'email:';

    public static function sendCode(string $email, string|int $account_type = '', string $key = 'un'): bool
    {
        $k = self::PREFIX . $key . $email;
        if (redis()->get($k) && env('APP_ENV') == 'prod' || env('APP_ENV') == 'dev') return true;
        $vcode = random_int(1000, 9999);
        redis()->set($k, $vcode, 900);
        return self::sendVcode($email, $vcode, $account_type);
    }

    public static function sendVcode(string $email, string|int $vcode, string|int $account_type): bool
    {
        $app_setting = api_cache()->getAppSetting($account_type);
        $name = $app_setting['app_name'] ?? 'fastapp';
        $content = html_format(TplMall::vcode(), [
            fastapp_t('email.v_0'),
            $app_setting['app_logo'],
            fastapp_t('email.v_1', ['name' => $name]),
            fastapp_t('email.v_2', ['name' => $name]),
            $vcode,
            fastapp_t('email.v_3'),
            fastapp_t('email.v_4', ['name' => $name]),
            fastapp_t('email.v_5', ['name' => $name]),
        ]);
        return self::sendMsg($email, $content, $account_type, fastapp_t('fastapp.un_vcode', ['vcode' => $vcode]));
    }

    public static function sendLoginMsg(int $user_id, string $device): bool
    {
        if (AccountLoginLog::query()->where(['user_id' => $user_id, 'agent' => $device])->exists()) return false;
        $ac = get_user_cache(['type', 'email', 'channel'], $user_id);
        if (!$ac['email']) return false;
        $app_setting = api_cache()->getAppSetting($ac['type']);
        $name = $app_setting['app_name'] ?? 'fastapp';

        $host = parse_url($app_setting['app_domain'])['host'];
        $channel = FastappChannel::query()->where('id', $ac['channel'])->value('key');
        if ($channel) $app_setting['app_domain'] = str_replace($host, $channel . '.' . $host, $app_setting['app_domain']);
        $content = html_format(TplMall::login(), [
            fastapp_t('email.l_0'),
            $app_setting['app_logo'],
            fastapp_t('email.l_1', ['device' => $device]),
            $ac['email'],
            fastapp_t('email.l_2', ['name' => $name, 'device' => $device]),
            fastapp_t('email.l_3', ['url' => $app_setting['app_domain'] . '/account/login/log']),
            fastapp_t('email.l_4', ['name' => $name, 'url' => $app_setting['app_domain'] . '/account/login/log']),
            fastapp_t('email.l_5', ['name' => $name, 'email' => $ac['email']]),
        ]);
        return self::sendMsg($ac['email'], $content, $ac['type']);
    }

    public static function sendMsg(string $email, string|int $content, string|int $account_type, string $altBody = ''): bool
    {
        $res = api_cache()->getConfigByGroupKey('email');
        $app_setting = api_cache()->getAppSetting($account_type);
        $name = $app_setting['app_name'] ?? 'fastapp';
        try {
            $mail = new PHPMailer(true);
            // 服务器配置
            $mail->isSMTP();
            $mail->Host = $res['smtp_host'];
            $mail->SMTPAuth = true;
            $mail->Username = $res['smtp_email'];
            $mail->Password = $res['smtp_code'];
            $mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;
            $mail->Port = $res['smtp_port'];
            $mail->setFrom($res['smtp_email'], $app_setting['app_name'] ?? $res['smtp_user']);       // 发件人
            $mail->addAddress($email, $email);
            $mail->addReplyTo($res['smtp_email'], $app_setting['app_name'] ?? $res['smtp_user']);    // 回复地址
            $mail->isHTML();
            $mail->Subject = $name;
            $mail->Body = $content;
            if ($altBody) $mail->AltBody = $altBody;
            return $mail->send();
        } catch (\Throwable $throwable) {
            console()->error($throwable->getMessage());
            sys_notify('邮件发送失败:' . $throwable->getMessage());
        }
        return false;

    }

    public static function validate(?string $email, string|int $vcode, bool $clean = true, string $key = 'un'): bool
    {
        if (!$email) throw new TipException(fastapp_t('account.invalid_fail'));
        if (config('app_env') == 'dev') return true;
        $k = self::PREFIX . $key . $email;
        $c = redis()->get($k);
        if ($c && $c == $vcode) {
            if ($clean) redis()->del($k);
            return true;
        }
        throw new TipException(fastapp_t('account.invalid_verification_error'));
    }
}